import _clonedeep from 'lodash/cloneDeep'
import { mapState } from 'vuex'
import varType from './varType'
import apiRequest from './apiRequest'
import Log from './Log'
import math from './math'
import numSplit from './numSplit'

export default {
  methods: {
    /**
     * 格式化金额  fmoney('12345') // 123,45
     * @param s {string|number}:  要分割的数字，合法数字
     * @param non {string}  分割符，默认逗号
     * @param num {number}  几位一分割，默认3位
     * @param decimal {number}  保留小数位数，默认不管（原来是多少就多少）
     * @returns {string}
     */
    fmoney(s, num = 3, decimal, non = ',') {
      return numSplit(s, non, num, decimal)
    },
    /**
     * 此方法参数为：
     * @param num1: 第一个需要操作的数字。

     * @param num2: 第二个需要操作的数字。

     * @param oper: 操作符，现在支持 +，-，*，/四个符号,只能为字符串。

     * @param precision: 浮点数精度(选填,默认2位,返回的计算结果的小数点位数)。
     *
     * this.math('1', '2', '+') // '3'
     * console.log('mmm', this.math('3', '2', '/', '0'))  3/2保留0位小数 即结果为2
     */
    math(num1, num2, oper, percision) {
      return math(num1, num2, oper, percision)
    },
    /**
     * 发送请求
     * @param {String} url *请求路径
     * @param {Object} param 请求内容
     * @param {Object} opts
     * @return Promise
     */
    post(url, param, opts = { showLoading: true }) {
      return apiRequest.post(url, param, opts)
    },
    postUseBlob(url, param, opts = { showLoading: true }) {
      return apiRequest.post(url, param, opts)
    },
    get(url, param, opts = { showLoading: true }) {
      return apiRequest.get(url, param, opts)
    },
    /**
     * 发送分页请求
     * const ret = await post('AL0441602', {"rcrd_id": "1", "mnplt_tpcd": "2"})
     * @param {String} transId *交易号
     * @param {Object} param 请求内容
     * @param {Object} opts
     * @return Promise
     */
    postPage(transId, param, pageSize, pageNum, opts = { showLoading: true }) {
      this.addPageParam(param, pageSize, pageNum)
      return new Promise((resolve, reject) => {
        this.post(transId, param, opts).then(ret => {
          const grpData = ret.data
          if (!grpData) {
            for (const [key] of Object.entries(ret)) {
              if (key.includes('grp')) {
                ret.data = ret[key]
                break
              }
            }
          }
          resolve(ret)
        }).catch(err => {
          reject(err)
        })
      })
    },
    /**
     * 深拷贝
     * var obj1 = {name: 'obj1'}
     * var obj2 = cloneDeep(obj1)
     * @param {Object} obj
     * @param {Boolean} isDeep 是否深拷贝，默认是
     * @return obj
     * */
    cloneDeep(obj, isDeep = true) {
      return _clonedeep(obj, isDeep)
    },
    /**
     * @param {Object} vm 当前vue对象
     * 关闭当前页面
     * */
    // close: function (path = this.$route.fullPath) {
    //     this.$store.dispatch('d2admin/page/close', {
    //         tagName: path
    //     })
    // },
    close: function() {
      this.$store.dispatch('d2admin/page/close', {
        tagName: this.$route.fullPath
      })
    },
    /**
     是否参数是否为空
     var obj = null
     isNull(obj) // true
     @param {Object} obj
     return {Boolean} true/false 为空返回true
     * */
    isNull(obj) {
      var type = varType(obj)
      if (type !== 'number' && !obj) {
        return true
      }
      if (type === 'array') {
        return !obj.length
      } else if (type === 'object') {
        return !Object.keys(obj).length
      }
      return false
    },
    /*
    添加分页参数 默认第一页，10条
    const param = {}
    addPageParam(param, 1, 1)
    console.log(param) // {page_jump: 1, rec_in_page: 1}
    @param {Object} param 你的请求参数
    @param {Integer} pageJump 多页查询跳转页码
    @param {Integer} recInPage 多页查询每页笔数
    * */
    addPageParam(param = {}, pageSize = 1, pageNum = 10) {
      Object.assign(param, {
        pageSize,
        pageNum
      })
    },
    /**
     校验选中数据个数
     @param {Object} data
     @param {String} type '0'不控 '1'单选; '2'一条以上
     * */
    isSelected(data, type = '0') {
      if (type === '0') {
        return true
      }
      if (this.isNull(data)) {
        this.$message.warning('请选中一条数据')
        return false
      }
      const len = data.length
      if (type === '1' && len !== 1) { // 必选且单选，eg:修改
        this.$message.warning('仅支持单选操作')
        return false
      } else if (type === '2' && !len) { // 必选且单选或多选
        this.$message.warning('请选择至少一条数据后操作')
        return false
      }
      return true
    },
    /**
     获取当前页面缓存信息
     * */
    getPageCache() {
      return this.opened.find(page => page.fullPath === this.current)
    },
    /**
     跳转页面
     解决将path相同fullPath不同的路径判断为不同页面重复打开问题
     @param {String,Object} url 父级路径path，推荐使用name，eg:"componentsName",{name:"componentsName"},{path:componentsPath}
     @param {Object} paramsData 传递过去新增的params,与原页面缓存的cache进行合并
     @param {Boolean} isClose 跳转后是否关闭当前子页面
     * */
    toPage(url = 'index', paramsData = null, isClose = true) {
      let parents_Page
      if (typeof (url) === 'string') {
        parents_Page = this.opened.find(page => page.name.toLowerCase() === url.toLowerCase())
      } else if (url.name) {
        parents_Page = this.opened.find(page => page.name.toLowerCase() === url.name.toLowerCase())
      } else if (url.path) {
        parents_Page = this.opened.find(page => page.fullPath.startsWith(url.path))
      }
      if (parents_Page) {
        const { name, params, query } = parents_Page
        if (paramsData) {
          // params = {...params, ...paramsData}
          params.sendData = paramsData
        }
        if (isClose) {
          this.close()
        }
        setTimeout(() => {
          console.log(name, params, query)
          this.$router.push({ name, params, query })
        }, 0)
      } else {
        this.close()
      }
    },
    varType,
    /**
     * 弹出提示
     * @param  {String} msg *提示信息
     * @param  {Function} fn 点击确定后续操作
     */
    $info(msg, fn = () => {
    }) {
      Log.info.call(this, msg, fn)
    },
    /**
     * 弹出警告
     * @param {String} msg 提示信息
     * @param  {Function} fn 点击确定后续操作
     */
    $warn(msg, fn = () => {
    }) {
      Log.warn.call(this, msg, fn)
    },
    /**
     * 弹出错误
     * @param {String} msg 提示信息
     * @param  {Function} fn 点击确定后续操作
     */
    $error(msg, fn = () => {
    }) {
      Log.error.call(this, msg, fn)
    },
    /**
     * 弹出确认提示
     * @param {String} msg 提示信息
     * @param {Function} fn 确认回调
     * @param {Function} clFn 取消回调
     */
    $sure(msg, fn = () => {
    }, clFn = () => {
    }) {
      Log.sure.call(this, msg, fn, clFn)
    },
    /**
     * 弹出确认提示
     * @param {String} tip 标题提示信息
     * @param {String} surebtnM 自定义确认按钮信息
     * @param {String} canclbtnM 自定义取消按钮信息
     * @param {String} msg 提示信息
     * @param {Function} fn 确认回调
     * @param {Function} clFn 取消回调
     */
    $sure2(msg, tip, surebtnM, canclbtnM, fn = () => {
    }, clFn = () => {
    }) {
      Log.sure2.call(this, msg, tip, surebtnM, canclbtnM, fn, clFn)
    },
    /**
     * 根据目标对象的键去赋值
     const source = {name: '1'}
     const target = {name: ''}
     this.assignData(source, target)
     console.log('target', target)
     * @param {Object} source 源对象
     * @param {Object} target 目标对象
     * @param {Boolean} flag 默认只对目标对象已有属性进行赋值，传false时将拷贝所有源属性到目标对象
     * @param {Boolean} ignoreNull 默认只对目标对象已有属性进行赋值，传false时将拷贝所有源属性到目标对象
     * return {Object} 返回目标对象
     *
     */
    assignData(source = {}, target = {}, flag = false, ignoreNull = false) {
      let assignObj = target
      if (flag) {
        assignObj = source
      }
      Object.keys(assignObj).forEach(key => {
        if (source.hasOwnProperty(key)) {
          const sourceValue = source[key]
          if (ignoreNull && this.isNull(sourceValue)) {
            return true
          }
          const type = this.varType(sourceValue)
          if (type === 'number') {
            target[key] = sourceValue === null ? null : sourceValue
          } else if (type === 'array') {
            let i = 0
            for (const _source of sourceValue) {
              if (this.varType(_source) === 'object') {
                const targetValue = target[key]
                if (targetValue) {
                  this.assignData(_source, targetValue[i++], flag)
                }
              }
            }
            target[key] = sourceValue
          } else if (type === 'object') {
            this.assignData(sourceValue, target[key], flag)
          } else {
            target[key] = sourceValue || ''
          }
        }
      })
      return target
    },
    /**
     * 重置对象
     * resetObj({name: '1'}) // {name: ''}
     * @param obj
     */
    resetObj(obj) {
      Object.keys(obj).forEach(key => {
        this.resetValue(obj, key)
      })
    },
    /**
     * 重置对象里某个key
     * resetValue({name: '1'}, 'name') // {name: ''}
     * @param obj
     * @param key
     */
    resetValue(obj, key) {
      const _obj = obj[key]
      const type = varType(_obj)
      if (type === 'string') {
        obj[key] = ''
      } else if (type === 'object') {
        this.resetObj(_obj)
      } else if (type === 'array') {
        _obj.splice(0, _obj.length)
        // _obj.splice(0, _obj.length, _obj[0])
        // this.resetValue(_obj, 0)
      } else {
        obj[key] = null
      }
    },
    /**
     * 按key值过滤对象
     * filterObj({a: '1',b:'2'}, ['a'], true) // {a: '1'}
     * @param {Object}    obj    源对象
     * @param {Array}    arr    需过滤的key数组
     * @param {Boolean} flag   正/反向过滤
     */
    filterObj(obj, arr, flag = true) {
      const result = {}
      Object.keys(obj).filter((key) => flag === true ? arr.includes(key) : !arr.includes(key)
      ).forEach((key) => {
        result[key] = obj[key]
      })
      return result
    },
    /**
     * 生成年份下拉列表
     * @param {Number} addNum  以当前年份为基准，向后取几年
     * @param {Number} startYear  最小年份，默认2008年起
     * @param {String} type  输出年份类型
     */
    genYearsOpts(addNum = 5, startYear = 2008, type = 'String') {
      const CUR_YEAR = new Date().getFullYear()
      const [maxYear, minYear] = [CUR_YEAR + Number(addNum), startYear]
      const obj = {}
      for (let i = minYear; i <= maxYear; i++) {
        obj[i] = type === 'String' ? String(i) : Number(i)
      }
      return obj
    },
    /**
     * bool转字符串
     * @param bool true/false
     * @returns {string} '1'/'0'
     */
    bool2str(bool) {
      return bool * 1 + ''
    }
  },
  computed: {
    ...mapState('d2admin/page', [
      'opened',
      'current'
    ]),
    isDetail() {
      const query = this.$route.query
      const pageType = query ? query.pageType : ''
      return pageType === 'detail'
    }
  }
}
